"""
Case Type   : 资源池化
Case Name   : 资源池化场景下, 只主机业务读写，踢出节点操作
Create At   : 2024-04-07
Owner       : songshixuan
Description :
    1、查看集群状态 cm_ctl query -Cv
    2、主节点进行写业务，踢出备一节点
    3、再次查看切换后集群状态 cm_ctl query -Cv
    4、恢复集群原始状态
Expect      :
    1、集群状态正常，数据库节点状态正常
    2、踢出备一节点成功
    3、节点状态不正常，备一down，业务没有中断
    4、恢复集群原始状态成功,集群状态正常
History     :
    1、2024-04-07 创建
"""


import os
import unittest
import time

from testcase.utils.ComThread import ComThread
from testcase.utils.CommonSH import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import macro
from yat.test import Node
from testcase.utils.Common import Common

Primary_SH = CommonSH('PrimaryDbUser')
Primary_ROOTSH= CommonSH('PrimaryRoot')

@unittest.skipIf(3 != Primary_SH.get_node_num(), '非1+2环境不执行')
class SharedStorage(unittest.TestCase):

    def setUp(self):
        self.log = Logger()
        self.com = Common()
        self.tpcc_user = Node('PrimaryRoot')
        self.log.info(f'-----{os.path.basename(__file__)} start-----')
        self.constant = Constant()

    def test_shared_storage(self):
        text = '-----step1:查看集群状态; expect:集群状态正常-----'
        self.log.info(text)
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('cluster_state   : Normal', status, '执行失败' + text)
        text = '-----step2:开始运行tpcc 120s; expect:运行成功，此处不做检查-----'
        self.log.info(text)
        start_tpcc = ComThread(self.com.start_tpcc,
                                 args=(self.tpcc_user,'/data/benchmarksql-5.0/run',
                                       './runBenchmark.sh props_write.pg'))
        start_tpcc.setDaemon(True)
        start_tpcc.start()
        status = Primary_ROOTSH.exec_cmd_under_root("ps -ux | grep './runBenchmark.sh' | grep -v -- '--color'")
        self.log.info(status)
        self.assertIn('props_write.pg', status, '执行失败' + text)
        time.sleep(10)
        text = '-----step3:尝试停止备节点1; expect:停止成功，备节点进入Unkown状态-----'
        self.log.info(text)
        status = Primary_SH.exec_cm_ctl(mode='stop', param='-n 2')
        self.log.info(status)
        self.assertIn('successfully.', status, '执行失败' + text)
        time.sleep(10)
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        # 2025-1-22 新增gstack抓取功能，当检测到异常的时候先粗暴的抓一下堆栈
        queryCmd = Primary_SH.exec_cmd_under_user("ps -ux | grep app/bin/gaussdb | grep -v -- '--color'")
        pid = queryCmd.split()[1]
        gsStackGaussdb = Primary_SH.exec_cmd_under_user("gstack " + pid)
        self.log.info(gsStackGaussdb)
        self.assertTrue('cluster_state   : Degraded' in status or 'cluster_state   : Unavailable' in status,
        '执行失败' + text)
        res1 = status.splitlines()[-1].split('|')[1].split('6002')[-1]
        self.assertIn('S Down    Unknown', res1, '执行失败' + text)
        text = '-----step4:查看tpcc是否存在; expect:tpcc进程运行-----'
        status = Primary_ROOTSH.exec_cmd_under_root("ps -ux | grep './runBenchmark.sh' | grep -v -- '--color'")
        self.log.info(status)
        self.assertIn('props_write.pg', status, '执行失败' + text)

    def tearDown(self):
        text = '-----step6:恢复环境为初始集群状态（不涉及主机切换，只需要尝试重启）; expect:成功-----'
        self.log.info(text)
        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        status = Primary_SH.check_cluster_core_status(status, wait_times=600)
        self.log.info(status)

        status = Primary_SH.exec_cm_ctl(mode='stop', param='')
        self.log.info(status)
        self.assertIn('successfully.', status, '执行失败' + text)

        status = Primary_SH.exec_cm_ctl(mode='start', param='')
        self.log.info(status)
        self.assertIn('successfully.', status, '执行失败' + text)

        recovery = Primary_SH.exec_cm_ctl(mode='switchover', param='-a')
        self.log.info(recovery)
        self.assertIn(self.constant.cm_switchover_success_msg, recovery,
                      '执行失败' + text)

        status = Primary_SH.exec_cm_ctl(mode='query', param='-Cv')
        self.log.info(status)
        self.assertIn('P Primary Normal',
                      status.splitlines()[-1].split('|')[0].split('6001')[-1],
                      '执行失败' + text)
        self.assertIn('S Standby Normal',
                      status.splitlines()[-1].split('|')[1].split('6002')[-1],
                      '执行失败' + text)
        self.assertIn('S Standby Normal',
                    status.splitlines()[-1].split('|')[2].split('6003')[-1],
                    '执行失败' + text)
        self.log.info(f'-----{os.path.basename(__file__)} end-----')

